// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © BOSWaves

//@version=5
indicator("Smart Money Trades Pro [BOSWaves]", overlay=true, max_lines_count=500)

// === Input Parameters ===
structurePeriod = input.int(20, "Structure Detection Period", minval=5, maxval=50, tooltip="Lookback period for swing point detection")
confirmationType = input.string("Body", "Break Confirmation", options=["Body", "Wick"], tooltip="Use candle body or wick for break confirmation")
showCHoCH = input.bool(true, "Display Change of Character", tooltip="Show CHoCH when trend changes")
showTrendBars = input.bool(true, "Color Trend Bars", tooltip="Color candles based on market structure trend")
showTable = input.bool(true, "Show Info Table", tooltip="Display current trade information table")
tablePosition = input.string("Top Right", "Table Position", options=["Top Left", "Top Right", "Bottom Left", "Bottom Right"])

// Enhanced Color Scheme
bullColor = input.color(#26A69A, "Bullish", group="Colors")
bearColor = input.color(#EF5350, "Bearish", group="Colors")
neutralColor = input.color(#9E9E9E, "Neutral", group="Colors")
successColor = input.color(#4CAF50, "Success/TP", group="Colors")
dangerColor = input.color(#F44336, "Danger/SL", group="Colors")
bgColor = input.color(color.new(#1E1E1E, 95), "Table Background", group="Colors")
textColor = input.color(color.white, "Table Text", group="Colors")

// === Market Structure Function ===
getMarketStructure() =>
    var float lastHigh = na
    var float lastLow = na
    var int lastHighBar = na
    var int lastLowBar = na
    var int trendDirection = 0
    var bool highBreakPending = false
    var bool lowBreakPending = false
    
    // Detect swing points
    swingHigh = ta.pivothigh(high, structurePeriod, structurePeriod)
    swingLow = ta.pivotlow(low, structurePeriod, structurePeriod)
    
    // Update swing levels
    if not na(swingHigh)
        lastHigh := swingHigh
        lastHighBar := bar_index - structurePeriod
        highBreakPending := true
        
    if not na(swingLow)
        lastLow := swingLow
        lastLowBar := bar_index - structurePeriod
        lowBreakPending := true
    
    // Check for breaks
    breakPrice = confirmationType == "Body" ? close : (trendDirection > 0 ? high : low)
    
    highBroken = false
    lowBroken = false
    
    if highBreakPending and not na(lastHigh)
        if (confirmationType == "Body" and close > lastHigh) or (confirmationType == "Wick" and high > lastHigh)
            highBroken := true
            highBreakPending := false
            
    if lowBreakPending and not na(lastLow)
        if (confirmationType == "Body" and close < lastLow) or (confirmationType == "Wick" and low < lastLow)
            lowBroken := true
            lowBreakPending := false
    
    // Update trend direction
    prevTrend = trendDirection
    if highBroken
        trendDirection := 1
    else if lowBroken
        trendDirection := -1
        
    isChoch = (prevTrend == -1 and trendDirection == 1) or (prevTrend == 1 and trendDirection == -1)
    
    [highBroken, lowBroken, lastHigh, lastLow, lastHighBar, lastLowBar, trendDirection, isChoch]

// Get market structure data
[bullBreak, bearBreak, structHigh, structLow, highBar, lowBar, trend, chochSignal] = getMarketStructure()

// === Enhanced Target Logic ===
var float entryLevel = na
var float tp1Level = na
var float tp2Level = na
var float tp3Level = na
var float stopLevel = na
var int tradeDirection = 0
var bool tp1Hit = false
var bool tp2Hit = false
var bool tp3Hit = false
var int lastTradeBar = na
var tp1line = line(na)
var tp2line = line(na)
var tp3line = line(na)
var stopline = line(na)
var entryline = line(na)
var box entryBox = na
var box riskBox = na
var box rewardBox = na

// Calculate dynamic range for targets
atr = ta.atr(14)
volatilityMultiplier = 2

if bullBreak and not na(structHigh)
    entryLevel := structHigh
    targetRange = atr * volatilityMultiplier
    tp1Level := entryLevel + targetRange * 0.8
    tp2Level := entryLevel + targetRange * 1.6
    tp3Level := entryLevel + targetRange * 2.8
    stopLevel := entryLevel - targetRange * 1.2
    tradeDirection := 1
    tp1Hit := false
    tp2Hit := false
    tp3Hit := false
    lastTradeBar := bar_index
    tp1line := line(na)
    tp2line := line(na)
    tp3line := line(na)
    stopline := line(na)
    entryline := line(na)
    box.delete(entryBox)
    box.delete(riskBox)
    box.delete(rewardBox)

if bearBreak and not na(structLow)
    entryLevel := structLow
    targetRange = atr * volatilityMultiplier
    tp1Level := entryLevel - targetRange * 0.8
    tp2Level := entryLevel - targetRange * 1.6
    tp3Level := entryLevel - targetRange * 2.8
    stopLevel := entryLevel + targetRange * 1.2
    tradeDirection := -1
    tp1Hit := false
    tp2Hit := false
    tp3Hit := false
    lastTradeBar := bar_index
    tp1line := line(na)
    tp2line := line(na)
    tp3line := line(na)
    stopline := line(na)
    entryline := line(na)
    box.delete(entryBox)
    box.delete(riskBox)
    box.delete(rewardBox)

// Check TP hits
if tradeDirection == 1
    if not tp1Hit and high >= tp1Level
        tp1Hit := true
        line.delete(tp1line)
        tp1line := line(na)
    if not tp2Hit and high >= tp2Level
        tp2Hit := true
        line.delete(tp2line)
        tp2line := line(na)
    if not tp3Hit and high >= tp3Level
        tp3Hit := true
        line.delete(tp3line)
        tp3line := line(na)
        line.delete(entryline)
        entryline := line(na)

if tradeDirection == -1
    if not tp1Hit and low <= tp1Level
        tp1Hit := true
        line.delete(tp1line)
        tp1line := line(na)
    if not tp2Hit and low <= tp2Level
        tp2Hit := true
        line.delete(tp2line)
        tp2line := line(na)
    if not tp3Hit and low <= tp3Level
        tp3Hit := true
        line.delete(tp3line)
        tp3line := line(na)
        line.delete(stopline)
        stopline := line(na)
        line.delete(entryline)
        entryline := line(na)

// Update line positions - keep lines visible
if not na(tp1line)
    tp1line.set_x2(bar_index + 15)
if not na(tp2line)
    tp2line.set_x2(bar_index + 15)
if not na(tp3line)
    tp3line.set_x2(bar_index + 15)
if not na(stopline)
    stopline.set_x2(bar_index + 15)
if not na(entryline)
    entryline.set_x2(bar_index + 15)

// Update boxes
if not na(entryBox)
    box.set_right(entryBox, bar_index + 15)
if not na(riskBox)
    box.set_right(riskBox, bar_index + 15)
if not na(rewardBox)
    box.set_right(rewardBox, bar_index + 15)

// Reset trade if stopped out
stopHit = (tradeDirection == 1 and low <= stopLevel) or (tradeDirection == -1 and high >= stopLevel)
if stopHit
    line.delete(stopline)
    line.delete(entryline)
    line.delete(tp1line)
    line.delete(tp2line)
    line.delete(tp3line)
    stopline := line(na)
    entryline := line(na)
    tp1line := line(na)
    tp2line := line(na)
    tp3line := line(na)
    tradeDirection := 0
    box.delete(entryBox)
    box.delete(riskBox)
    box.delete(rewardBox)

// === Visualizations ===

// Enhanced trend coloring with gradient effect
trendBarColor = showTrendBars ? 
     (trend == 1 ? color.new(bullColor, 10) : 
      trend == -1 ? color.new(bearColor, 10) : 
      color.new(neutralColor, 60)) : na
      
barcolor(trendBarColor)

// Structure break lines and labels with enhanced styling
if bullBreak and not na(structHigh) and not na(highBar)
    breakLine = line.new(highBar, structHigh, bar_index, structHigh, 
             color=color.new(bullColor, 30), width=2, style=line.style_dotted, extend=extend.none)
    labelText = chochSignal and showCHoCH ? "CHoCH ↗" : "BOS ↗"
    // Position label above the high with offset
    labelOffset = ta.highest(high, 5) + (atr * 0.5)
    breakLabel = label.new(bar_index, labelOffset, labelText, 
              color=color.new(bullColor, 0), textcolor=color.white, 
              style=label.style_label_down, size=size.normal, force_overlay=true)

if bearBreak and not na(structLow) and not na(lowBar)
    breakLine = line.new(lowBar, structLow, bar_index, structLow, 
             color=color.new(bearColor, 30), width=2, style=line.style_dotted, extend=extend.none)
    labelText = chochSignal and showCHoCH ? "CHoCH ↘" : "BOS ↘"
    // Position label below the low with offset
    labelOffset = ta.lowest(low, 5) - (atr * 0.5)
    breakLabel = label.new(bar_index, labelOffset, labelText, 
              color=color.new(bearColor, 0), textcolor=color.white, 
              style=label.style_label_up, size=size.normal, force_overlay=true)

// Enhanced target visualization with zones
if tradeDirection != 0 and not na(entryLevel) and bar_index == lastTradeBar
    lineExtend = 15
    
    // Entry level with zone
    entryline := line.new(bar_index, entryLevel, bar_index + lineExtend, entryLevel, 
             color=color.new(color.white, 20), width=2, style=line.style_solid)
    
    // Create visual zones
    if tradeDirection == 1
        // Risk zone (Entry to Stop)
        riskBox := box.new(bar_index, entryLevel, bar_index + lineExtend, stopLevel,
                 border_color=color.new(dangerColor, 80), border_width=1,
                 bgcolor=color.new(dangerColor, 95))
        
        // Reward zone (Entry to TP3)
        rewardBox := box.new(bar_index, entryLevel, bar_index + lineExtend, tp3Level,
                 border_color=color.new(successColor, 80), border_width=1,
                 bgcolor=color.new(successColor, 97))
    else
        // Risk zone (Entry to Stop)
        riskBox := box.new(bar_index, entryLevel, bar_index + lineExtend, stopLevel,
                 border_color=color.new(dangerColor, 80), border_width=1,
                 bgcolor=color.new(dangerColor, 95))
        
        // Reward zone (Entry to TP3)
        rewardBox := box.new(bar_index, entryLevel, bar_index + lineExtend, tp3Level,
                 border_color=color.new(successColor, 80), border_width=1,
                 bgcolor=color.new(successColor, 97))
    
    // Take profit levels with progressive styling
    if not tp1Hit
        tp1line := line.new(bar_index, tp1Level, bar_index + lineExtend, tp1Level,
                 color=color.new(successColor, 40), width=1, style=line.style_dashed)
        // Position TP labels to the right with extra offset
        label.new(bar_index + lineExtend + 2, tp1Level, " TP1: " + str.tostring(tp1Level, format.mintick), 
                 color=color.new(color.white, 100), textcolor=successColor,
                 style=label.style_label_left, size=size.small)
    
    if not tp2Hit
        tp2line := line.new(bar_index, tp2Level, bar_index + lineExtend, tp2Level,
                 color=color.new(successColor, 30), width=1, style=line.style_dashed)
        label.new(bar_index + lineExtend + 2, tp2Level, " TP2: " + str.tostring(tp2Level, format.mintick), 
                 color=color.new(color.white, 100), textcolor=successColor,
                 style=label.style_label_left, size=size.small)
    
    if not tp3Hit
        tp3line := line.new(bar_index, tp3Level, bar_index + lineExtend, tp3Level,
                 color=color.new(successColor, 20), width=2, style=line.style_solid)
        label.new(bar_index + lineExtend + 2, tp3Level, " TP3: " + str.tostring(tp3Level, format.mintick), 
                 color=color.new(color.white, 100), textcolor=successColor,
                 style=label.style_label_left, size=size.small)
    
    // Stop loss with emphasis
    stopline := line.new(bar_index, stopLevel, bar_index + lineExtend, stopLevel, 
             color=color.new(dangerColor, 20), width=2, style=line.style_solid)
    label.new(bar_index + lineExtend + 2, stopLevel, " SL: " + str.tostring(stopLevel, format.mintick), 
             color=color.new(color.white, 100), textcolor=dangerColor,
             style=label.style_label_left, size=size.small)

// Signal shapes with enhanced visibility
plotshape(bullBreak, "Bull Signal", shape.triangleup, location.belowbar, 
          color=color.new(bullColor, 0), size=size.normal)
plotshape(bearBreak, "Bear Signal", shape.triangledown, location.abovebar, 
          color=color.new(bearColor, 0), size=size.normal)

// === Information Table ===
if showTable and tradeDirection != 0
    tablePos = tablePosition == "Top Left" ? position.top_left : 
               tablePosition == "Top Right" ? position.top_right :
               tablePosition == "Bottom Left" ? position.bottom_left : position.bottom_right
    
    infoTable = table.new(tablePos, 3, 8, bgcolor=bgColor, 
                         frame_color=color.new(color.gray, 50), frame_width=1,
                         border_color=color.new(color.gray, 70), border_width=1)
    
    // Header
    table.cell(infoTable, 0, 0, "TRADE INFO", text_color=textColor, bgcolor=color.new(color.gray, 80),
              text_size=size.normal, text_halign=text.align_center)
    table.merge_cells(infoTable, 0, 0, 2, 0)
    
    // Trade Direction
    directionText = tradeDirection == 1 ? "LONG ↗" : "SHORT ↘"
    directionColor = tradeDirection == 1 ? bullColor : bearColor
    table.cell(infoTable, 0, 1, "Direction", text_color=color.new(textColor, 30), text_size=size.small)
    table.cell(infoTable, 1, 1, directionText, text_color=directionColor, text_size=size.normal, text_halign=text.align_right)
    table.merge_cells(infoTable, 1, 1, 2, 1)
    
    // Entry Price
    table.cell(infoTable, 0, 2, "Entry", text_color=color.new(textColor, 30), text_size=size.small)
    table.cell(infoTable, 1, 2, str.tostring(entryLevel, format.mintick), 
              text_color=textColor, text_size=size.small, text_halign=text.align_right)
    table.merge_cells(infoTable, 1, 2, 2, 2)
    
    // Stop Loss
    slDistance = math.abs(entryLevel - stopLevel)
    slPercent = (slDistance / entryLevel) * 100
    table.cell(infoTable, 0, 3, "Stop Loss", text_color=color.new(dangerColor, 20), text_size=size.small)
    table.cell(infoTable, 1, 3, str.tostring(stopLevel, format.mintick), 
              text_color=dangerColor, text_size=size.small, text_halign=text.align_right)
    table.cell(infoTable, 2, 3, "(-" + str.tostring(slPercent, "#.##") + "%)", 
              text_color=color.new(dangerColor, 30), text_size=size.tiny, text_halign=text.align_right)
    
    // TP1
    tp1Distance = math.abs(tp1Level - entryLevel)
    tp1Percent = (tp1Distance / entryLevel) * 100
    tp1Status = tp1Hit ? " ✓" : ""
    tp1Color = tp1Hit ? color.new(successColor, 50) : successColor
    table.cell(infoTable, 0, 4, "TP 1" + tp1Status, text_color=color.new(tp1Color, 20), text_size=size.small)
    table.cell(infoTable, 1, 4, str.tostring(tp1Level, format.mintick), 
              text_color=tp1Color, text_size=size.small, text_halign=text.align_right)
    table.cell(infoTable, 2, 4, "(+" + str.tostring(tp1Percent, "#.##") + "%)", 
              text_color=color.new(tp1Color, 30), text_size=size.tiny, text_halign=text.align_right)
    
    // TP2
    tp2Distance = math.abs(tp2Level - entryLevel)
    tp2Percent = (tp2Distance / entryLevel) * 100
    tp2Status = tp2Hit ? " ✓" : ""
    tp2Color = tp2Hit ? color.new(successColor, 50) : successColor
    table.cell(infoTable, 0, 5, "TP 2" + tp2Status, text_color=color.new(tp2Color, 20), text_size=size.small)
    table.cell(infoTable, 1, 5, str.tostring(tp2Level, format.mintick), 
              text_color=tp2Color, text_size=size.small, text_halign=text.align_right)
    table.cell(infoTable, 2, 5, "(+" + str.tostring(tp2Percent, "#.##") + "%)", 
              text_color=color.new(tp2Color, 30), text_size=size.tiny, text_halign=text.align_right)
    
    // TP3
    tp3Distance = math.abs(tp3Level - entryLevel)
    tp3Percent = (tp3Distance / entryLevel) * 100
    tp3Status = tp3Hit ? " ✓" : ""
    tp3Color = tp3Hit ? color.new(successColor, 50) : successColor
    table.cell(infoTable, 0, 6, "TP 3" + tp3Status, text_color=color.new(tp3Color, 20), text_size=size.small)
    table.cell(infoTable, 1, 6, str.tostring(tp3Level, format.mintick), 
              text_color=tp3Color, text_size=size.small, text_halign=text.align_right)
    table.cell(infoTable, 2, 6, "(+" + str.tostring(tp3Percent, "#.##") + "%)", 
              text_color=color.new(tp3Color, 30), text_size=size.tiny, text_halign=text.align_right)
    
    // Risk/Reward Ratio
    avgReward = (tp1Distance + tp2Distance + tp3Distance) / 3
    rrRatio = avgReward / slDistance
    table.cell(infoTable, 0, 7, "Risk/Reward", text_color=color.new(textColor, 30), text_size=size.small)
    table.cell(infoTable, 1, 7, "1:" + str.tostring(rrRatio, "#.##"), 
              text_color=color.new(successColor, 0), text_size=size.normal, text_halign=text.align_right)
    table.merge_cells(infoTable, 1, 7, 2, 7)